import type {
  ComputeContext,
  CreateCrudOptionsProps,
  CreateCrudOptionsRet,
  CrudExpose,
  ScopeContext,
} from '@fast-crud/fast-crud';

import type { FormRulesExt } from '#/api';
import type { DefInterfaceModel } from '#/api/devOperation/ops/model/defInterfaceModel';
import type { ActionEnum } from '#/enums/commonEnum';

import { ref } from 'vue';
import { Codemirror } from 'vue-codemirror';
import { useRouter } from 'vue-router';

import { useAccess } from '@vben/access';
import { $t } from '@vben/locales';

import { java } from '@codemirror/lang-java';
import { oneDark } from '@codemirror/theme-one-dark';
import { compute } from '@fast-crud/fast-crud';

import { RuleType } from '#/api';
import { DefInterfaceApi } from '#/api/devOperation/ops/defInterface';
import { InterfaceExecModeEnum } from '#/enums/base';
import { DictEnum, RouteEnum } from '#/enums/commonEnum';
import { PermCode } from '#/enums/perm';
import {
  backendDict,
  createdTimeColumn,
  deleteButton,
  indexColumn,
  STATE_CONSTANT_DICT,
} from '#/plugins/fast-crud/common';

const logExtensions = [java(), oneDark];
const { hasPermission } = useAccess();
const permCode = PermCode.devOperation.ops.defInterface;

export function createCrudOptions(
  props: CreateCrudOptionsProps<DefInterfaceModel.DefInterfaceResultVO, any>,
): CreateCrudOptionsRet<DefInterfaceModel.DefInterfaceResultVO> {
  const selectedRowKeys = ref<string[]>([]);

  const { push } = useRouter();
  return {
    crudOptions: {
      request: {
        pageRequest: DefInterfaceApi.pageRequest,
        addRequest: DefInterfaceApi.addRequest,
        editRequest: DefInterfaceApi.editRequest,
        delRequest: DefInterfaceApi.delRequest,
        infoRequest: DefInterfaceApi.infoRequest,
      },
      form: {
        col: { span: 24 },
        wrapper: { is: 'a-drawer', draggable: false },
      },
      actionbar: {
        buttons: {
          add: { show: hasPermission(permCode.add) },
          ...deleteButton({
            crudExpose: props.crudExpose,
            selectedRowKeys,
            role: permCode.delete,
            removeFn: DefInterfaceApi.remove,
          }),
        },
      },
      table: {
        striped: true,
        rowKey: 'id',
        rowSelection: {
          type: 'checkbox',
          selectedRowKeys,
          onChange: (changed: string[]) => {
            selectedRowKeys.value = changed;
          },
        },
      },
      rowHandle: {
        width: '250px',
        buttons: {
          settings: {
            text: '接口设置',
            type: 'link',
            show: hasPermission(permCode.property),
            click(context) {
              push({
                name: RouteEnum.BASIC_MSG_PROPERTY,
                params: { id: context.row.id },
                query: { name: context.row.name },
              });
            },
          },
          view: { dropdown: true },
          edit: { show: hasPermission(permCode.edit) },
          remove: {
            show: hasPermission(permCode.delete),
          },
          copy: { show: hasPermission(permCode.add) },
        },
      },
      columns: {
        ...indexColumn(props.crudExpose),
        code: {
          title: $t('devOperation.ops.defInterface.code'),
          type: 'text',
          search: { show: true },
        },
        name: {
          title: $t('devOperation.ops.defInterface.name'),
          type: 'text',
          search: { show: true },
        },
        execMode: {
          title: $t('devOperation.ops.defInterface.execMode'),
          type: 'dict-radio',
          dict: backendDict(DictEnum.InterfaceExecModeEnum),
          search: { show: true },
          addForm: {
            value: InterfaceExecModeEnum.IMPL_CLASS,
          },
          form: {
            helper: { text: '代码中由Spring管理的实现类' },
            component: {
              optionName: 'a-radio-button',
            },
          },
        },
        script: {
          title: $t('devOperation.ops.defInterface.script'),
          type: 'text',
          form: {
            helper: { text: 'java/groovy 脚本' },
            show: compute((context: ComputeContext) => {
              return context.form.execMode === InterfaceExecModeEnum.SCRIPT;
            }),
            render: (scope: ScopeContext) => {
              return (
                <>
                  <Codemirror
                    autofocus={true}
                    disabled={scope.mode === 'view'}
                    extensions={logExtensions}
                    indentWithTab={true}
                    style={{ height: '200px' }}
                    tabSize={2}
                    v-model:modelValue={scope.form.script}
                  />
                </>
              );
            },
          },
          viewForm: { ignoreUseCellComponent: true },
          column: { show: false },
        },
        implClass: {
          title: $t('devOperation.ops.defInterface.implClass'),
          type: 'text',
          form: {
            show: compute((context: ComputeContext) => {
              return context.form.execMode === InterfaceExecModeEnum.IMPL_CLASS;
            }),
          },
          column: { show: false },
        },
        state: {
          title: $t('devOperation.ops.defInterface.state'),
          type: 'dict-radio',
          dict: STATE_CONSTANT_DICT,
          search: { show: true },
          addForm: {
            value: true,
          },
          form: {
            component: {
              optionName: 'a-radio-button',
            },
          },
        },
        ...createdTimeColumn({}),
      },
    },
  };
}

export const frontRules = (
  _crudExpose: CrudExpose,
  _mode: ActionEnum,
): FormRulesExt => {
  return {
    implClass: {
      type: RuleType.and,
      rules: [
        {
          trigger: 'blur',
          type: 'string',
          required: true,
          message: `不能为空`,
        },
      ],
    },
    script: {
      type: RuleType.and,
      rules: [
        {
          trigger: 'blur',
          required: true,
          type: 'string',
          message: `不能为空`,
        },
      ],
    },
  };
};
